package org.lojzes.lojzesframework.handler;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.lojzes.lojzesframework.annotation.Arguments;
import org.lojzes.lojzesframework.annotation.ReturnType;
import org.lojzes.lojzesframework.freemark.FreeMarkFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

public class PreDaoHandler implements InvocationHandler {
	private boolean showSql = false;
	@Autowired
	private JdbcTemplate jdbcTemplate;

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// 返回值
		Object returnObj = null;
		// SQL模板参数
		Map<String, Object> sqlParamsMap = new HashMap<String, Object>();
		// 1.获取模板参数
		obtainSqlParamsMap(sqlParamsMap, method, args);

		// 2.获取可执行sql
		String executeSql = obtainTemplateSql(method, sqlParamsMap);
		if(showSql){
			System.out.println("preDao sql==>>"+executeSql);
		}
		// 3.执行查询结果
		returnObj = executeObject(method, executeSql);

		return returnObj;
	}

	private Object executeObject(Method method, String executeSql) {
		//判断是否是insert/update操作
		if(isUpIns(executeSql)){
			jdbcTemplate.execute(executeSql);
		}
		Class<?> returnType = method.getReturnType();
		if(returnType.isPrimitive()){
			Number number = (Number)jdbcTemplate.queryForObject(executeSql, returnType);
			String vlaueR = returnType.getCanonicalName();
			if("int".equals(vlaueR)){
				return number.intValue();
			}else if("double".equals(vlaueR)){
				return number.doubleValue();
			}else if("long".equals(vlaueR)){
				return number.longValue();
			}
		 }
		if(String.class==returnType){
			String stringR = (String)jdbcTemplate.queryForObject(executeSql, returnType);
			return stringR;
		}
		if (returnType == List.class && method.isAnnotationPresent(ReturnType.class)) {
			ReturnType rtype = method.getAnnotation(ReturnType.class);
			return jdbcTemplate.query(executeSql,BeanPropertyRowMapper.newInstance(rtype.value()));
		}
		return null;
	}

	private boolean isUpIns(String executeSql) {
		 return (executeSql.startsWith("update")||executeSql.startsWith("insert"))?true:false;
	}

	/**
	 * 获取方法参数map
	 * 
	 * @param sqlParamsMap
	 * @param method
	 * @param args
	 * @throws Exception
	 */
	private void obtainSqlParamsMap(Map<String, Object> sqlParamsMap, Method method, Object[] args) throws Exception {

		if (method.isAnnotationPresent(Arguments.class)&&args==null) {
			throw new Exception("===>>没有定义@Arguments参数，请检查配置！");
		}
		if(method.isAnnotationPresent(Arguments.class)){
			Arguments annotation = method.getAnnotation(Arguments.class);
			if (annotation.value().length != args.length) {
				throw new Exception("===>>@Arguments参数个数与方法参数个数不一致，请检查配置！");
			}
			int index = 0;
			for (String paramerName : annotation.value()) {
				sqlParamsMap.put(paramerName, args[index]);
				index++;
			}
		}
	}

	private String obtainTemplateSql(Method method, Map<String, Object> sqlParamsMap) {
		String sqlTpl = method.getDeclaringClass().getSimpleName() + "_" + method.getName() + ".sql";
		return FreeMarkFactory.parseTemplate(sqlTpl, sqlParamsMap);
	}

	public boolean isShowSql() {
		return showSql;
	}

	public void setShowSql(boolean showSql) {
		this.showSql = showSql;
	}

}
